import Mn from 'backbone.marionette';

import {hideLoader, showLoader} from 'tools';
import FormBehavior from '../../base/behaviors/FormBehavior.js';
import DateWidget from '../../widgets/DateWidget.js';
import InputWidget from '../../widgets/InputWidget.js';
import Select2Widget from '../../widgets/Select2Widget.js';
import Radio from 'backbone.radio';
import {
    HtModelFieldsLinker,
    TTCModelFieldsLinker
} from "../compute/FieldsLinkers";



const BaseExpenseFormView = Mn.View.extend({
    behaviors: [FormBehavior],
    template: require('./templates/ExpenseFormView.mustache'),
	regions: {
        'category': '.category',
		'date': '.date',
		'type_id': '.type_id',
		'description': '.description',
        'invoice_number': '.invoice_number',
        'fill_mode': '.fill_mode',
		'ht': '.ht',
		'manual_ttc': '.manual_ttc',
		'tva': '.tva',
        'ttc_readonly': '.ttc_readonly',
        'tva_rate': '.tva_rate',
		'business_link': '.business_link',
        'supplier_id': '.supplier_id',
        'files': '.files',
    },
    // Bubble up child view events
    //
    childViewTriggers: {
        'change': 'data:modified',
    },
    childViewEvents: {
        'finish': 'onChildChange',
    },
    onBeforeSync: showLoader,
    onFormSubmitted: hideLoader,
    initialize(){
        // Common initialization.
        var channel = Radio.channel('config');
        this.type_options = this.getTypeOptions();
        this.suppliers_options = channel.request('get:options', 'suppliers');
        console.log('this.type_options', this.getTypeOptions());
        this.today = channel.request(
            'get:options',
            'today',
        );
        // If we have no type (eg: new expense form), adopt the first option of
        // the select list.
        if (this.model.get('type_id') === undefined) {
            this.model.set('type_id', String(this.type_options[0].id));
        }
    },
    showFilesSelect(){
        var channel = Radio.channel('facade');
        let attachments = channel.request('get:collection', 'attachments');
        const view = new Select2Widget({
            title: "Justificatifs",
            options: attachments.asSelectOptions(),
            field_name: "files",
            field_id: "select2-files",
            multiple: true,
            value: this.model.get('files'),
            placeholder: "Choisir un ou plusieurs justificatifs déjà téléversés",
        });
        this.showChildView('files', view);
    },
    /** Render/Update the form fields related to amounts
     *
     * Optionaly, the fields to be rendered can be restricted via fields argument.
     * Other will remain untouched.
     *
     * @param fields String
     */
    renderAmountFields(fields) {
        const show = (function(areaName, view) {
            if ((fields === undefined) || fields.includes(areaName)) {
                this.showChildView(areaName, view);
            }
        }).bind(this);

        const htParams = {
            value: this.model.get('ht'),
            title: 'Montant HT',
            field_name: 'ht',
            addon: "€",
            required: true,
        }

        const tvaParams = {
            value: this.model.get('tva'),
            title: 'Montant TVA',
            field_name: 'tva',
            addon: "€",
            required: true,
        }

        const manual_ttcParams = {
            value: 0,
            title: 'Montant TTC',
            field_name: 'manual_ttc',
            addon: "€",
            required: true,
        }

        const ttc_readonlyParams = {
            title: 'Montant TTC',
            addon: "€",
            field_name: "ttc_readonly",
            value: this.model.get('ttc_readonly'),
        }

        if (this.model.hasTvaOnMargin()) {
            tvaParams.value = 0;
            htParams.value = 0;

            manual_ttcParams.value = this.model.get('manual_ttc');

        } else if (!this.model.hasDeductibleTva()) {
            manual_ttcParams.value = 0;
            tvaParams.value = 0;
            htParams.title = 'Montant TTC'
        } else {
            // regular mode (no TVA/margin neither telecom-like expense)

            if (this.model.get('fill_mode') === 'ht') {
                ttc_readonlyParams.editable = false;
                ttc_readonlyParams.description = "Le montant TTC est calculé";
                htParams.editable = true;
            } else {  // fill_mode === 'ttc'
                ttc_readonlyParams.editable = true;
                htParams.description = "Le montant HT est calculé";
                htParams.editable = false;
            }
        }

        let view = new InputWidget(manual_ttcParams);
        show('manual_ttc', view);
        view = new InputWidget(htParams);
        show('ht', view);
        view = new InputWidget(tvaParams);
        show('tva', view);

        if (! this.model.requiresTtcInput()) {
            view = new InputWidget({
                value: this.model.get('tva_rate'),
                title: 'Taux TVA',
                placeholder: "Taux de TVA en %",
                field_name: "tva_rate",
                addon: "%",
                description: "Le montant de TVA peut être calculé à partir de ce taux",
            });
            show('tva_rate', view);

            view = new InputWidget(ttc_readonlyParams);
            show('ttc_readonly', view);
        } else {
            this.getRegion('ttc_readonly').reset();
            this.getRegion('tva_rate').reset();
        }

    },
    onRender(){
        var view;
        view = new DateWidget({
            date: this.model.get('date'),
            title: "Date",
            field_name: "date",
            default_value: this.today,
            required: true,
        });
        this.showChildView("date", view);

        view = new Select2Widget({
            value: this.model.get('supplier_id'),
            title: 'Fournisseur',
            field_name: 'supplier_id',
            field_id: "supplier_id", // Nécessaire pour résoudre le bug de nav au clavier
            options: this.suppliers_options,
            placeholder: 'Choisir un fournisseur',
        });
        this.showChildView('supplier_id', view);

        view = new InputWidget({
            value: this.model.get('invoice_number'),
            title: 'Numéro de la facture',
            field_name: 'invoice_number',
        });
        this.showChildView('invoice_number', view);

        let previousType = this.model.get('type_id');
        view = this.renderTypeSelect();

        // Syncs model to allow proppper rendering of the form based on wether
        // we have TVA or not.
        this.triggerMethod('data:modified', 'type_id', view.getCurrentValues()[0])
        if (previousType != view.getCurrentValues()[0]) {
            /* re-render to get correct hide/show of amount fields
             * Handle cases where we changed tab and default type
             * option of the new tab has different field presence requirements (tva/ht/ttc)
             * than previous tab's one.
             * A bit hackish
             */
            this.render();
            return;
        }
        this.renderAmountFields();
        this.showFilesSelect();
    },
    renderTypeSelect(){
        const view = new Select2Widget({
            value: this.model.get('type_id'),
            title: 'Type de dépense',
            field_name: 'type_id',
            field_id: "type_id", // Nécessaire pour résoudre le bug de nav au clavier
            options: this.type_options,
            id_key: 'id',
            required: true,
        });
        this.showChildView('type_id', view);
        return view;
    },
    onChildChange(field_name, value) {
        this.triggerMethod('data:modified', field_name, value);

        if (field_name == 'type_id') {
            this.render();
        } else if (field_name == 'files') {
            this.triggerMethod('files:changed');

            /* Refresh totally the files widget, to workaround two select2 issues:
            * - stores in certain circonstances empty ids (unexplained)
            * - let the dropdown open but at the wrong place (when the popin gets
            * resized when preview pane is added/removed)
            */
            this.showFilesSelect();
        }
        if (field_name === 'fill_mode') {
            this.renderAmountFields();
            this.showFillModeChoice();
        }
        if (field_name === 'category'){
            this.type_options = this.getTypeOptions();
            this.renderTypeSelect();
        }

        this.onAmountsChange(field_name, value);
    },
    onAmountsChange(field_name, value) {
        let  linker;
        if (this.model.get('fill_mode') === 'ht') {
            linker = HtModelFieldsLinker;
        } else {
            linker = TTCModelFieldsLinker;
        }
        let prevValue = this.model.get(field_name);
        if ((prevValue !== value) && (value !== '')) {
            this.triggerMethod('data:modified', field_name, value);
            const changedFields = linker.reactToFieldChange(field_name, this.model);
            this.renderAmountFields(changedFields);
        }
    },
    afterSerializeForm(datas){
        let modifiedDatas = _.clone(datas);

        /* We also want the category to be pushed to server,
         * even if not present as form field
         */
        modifiedDatas['category'] = this.model.get('category');

        // Hack to allow setting those fields to null.
        // Otherwise $.serializeForm skips <select> with no value selected
        modifiedDatas['customer_id'] = this.model.get('customer_id');
        modifiedDatas['project_id'] = this.model.get('project_id');
        modifiedDatas['business_id'] = this.model.get('business_id');

        return modifiedDatas;
    },
    templateContext: function(){
        let hasTvaOnMargin = this.model.hasTvaOnMargin();
        return {
            button_title: this.getOption('buttonTitle'),
            add: this.getOption('add'),
            hidden_ht: hasTvaOnMargin,
            hidden_tva: this.model.requiresTtcInput(),
            hidden_manual_ttc: ! hasTvaOnMargin,
        };
    },
});
export default BaseExpenseFormView;
